﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace BooruViewer.Models
{
    public partial class Derpi
    {
        [JsonProperty("search")]
        public List<Search> Search { get; set; }

        [JsonProperty("total")]
        public long Total { get; set; }

        [JsonProperty("interactions")]
        public List<object> Interactions { get; set; }
    }

    public class Search
    {
        [JsonProperty("id")]
        public string Id { get; set; }

        [JsonProperty("created_at")]
        public System.DateTime CreatedAt { get; set; }

        [JsonProperty("updated_at")]
        public System.DateTime UpdatedAt { get; set; }

        [JsonProperty("duplicate_reports")]
        public List<DuplicateReport> DuplicateReports { get; set; }

        [JsonProperty("first_seen_at")]
        public System.DateTime? FirstSeenAt { get; set; }

        [JsonProperty("uploader_id")]
        public string UploaderId { get; set; }

        [JsonProperty("score")]
        public long Score { get; set; }

        [JsonProperty("comment_count")]
        public long? CommentCount { get; set; }

        [JsonProperty("width")]
        public long Width { get; set; }

        [JsonProperty("height")]
        public long Height { get; set; }

        [JsonProperty("file_name")]
        public string FileName { get; set; }

        [JsonProperty("description")]
        public string Description { get; set; }

        [JsonProperty("uploader")]
        public string Uploader { get; set; }

        [JsonProperty("image")]
        public string Image { get; set; }

        [JsonProperty("upvotes")]
        public long Upvotes { get; set; }

        [JsonProperty("downvotes")]
        public long Downvotes { get; set; }

        [JsonProperty("faves")]
        public long Faves { get; set; }

        [JsonProperty("tags")]
        public string Tags { get; set; }

        [JsonProperty("tag_ids")]
        public List<string> TagIds { get; set; }

        [JsonProperty("aspect_ratio")]
        public double AspectRatio { get; set; }

        [JsonProperty("original_format")]
        public string OriginalFormat { get; set; }

        [JsonProperty("mime_type")]
        public string MimeType { get; set; }

        [JsonProperty("sha512_hash")]
        public string Sha512Hash { get; set; }

        [JsonProperty("orig_sha512_hash")]
        public string OrigSha512Hash { get; set; }

        [JsonProperty("source_url")]
        public string SourceUrl { get; set; }

        [JsonProperty("representations")]
        public Representations Representations { get; set; }

        [JsonProperty("is_rendered")]
        public bool IsRendered { get; set; }

        [JsonProperty("is_optimized")]
        public bool IsOptimized { get; set; }
    }

    public partial class DuplicateReport
    {
        [JsonProperty("id")]
        public long? Id { get; set; }

        [JsonProperty("state")]
        public string State { get; set; }

        [JsonProperty("reason")]
        public string Reason { get; set; }

        [JsonProperty("image_id")]
        public long? ImageId { get; set; }

        [JsonProperty("duplicate_of_image_id")]
        public long? DuplicateOfImageId { get; set; }

        [JsonProperty("user_id")]
        public object UserId { get; set; }

        [JsonProperty("modifier_id")]
        public long? ModifierId { get; set; }

        [JsonProperty("created_at")]
        public System.DateTime? CreatedAt { get; set; }
    }

    public partial class Representations
    {
        [JsonProperty("thumb_tiny")]
        public string ThumbTiny { get; set; }

        [JsonProperty("thumb_small")]
        public string ThumbSmall { get; set; }

        [JsonProperty("thumb")]
        public string Thumb { get; set; }

        [JsonProperty("small")]
        public string Small { get; set; }

        [JsonProperty("medium")]
        public string Medium { get; set; }

        [JsonProperty("large")]
        public string Large { get; set; }

        [JsonProperty("tall")]
        public string Tall { get; set; }

        [JsonProperty("full")]
        public string Full { get; set; }

        [JsonProperty("webm")]
        public string Webm { get; set; }

        [JsonProperty("mp4")]
        public string Mp4 { get; set; }
    }

    public partial class Derpi
    {
        public static Derpi FromJson(string json) => JsonConvert.DeserializeObject<Derpi>(json, DerpiConverter.Settings);
    }

    public static class SerializeDerpi
    {
        public static string ToJson(this Derpi self) => JsonConvert.SerializeObject(self, DerpiConverter.Settings);
    }

    public class DerpiConverter
    {
        public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
        {
            MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
            DateParseHandling = DateParseHandling.None,
        };
    }

    public static class DerpiHelpers
    {
        /// <summary>
        /// Coverts the Derpi object to a list of BImage objects
        /// </summary>
        /// <param name="derpi"></param>
        /// <returns></returns>
        public static List<BImage> DerpiToImages(this Derpi derpi)
        {
            List<BImage> imgs = new List<BImage>();

            foreach (var d in derpi.Search)
            {
                var tags = d.Tags.Replace(", ",",").Split(',');

                imgs.Add(new BImage(
                    d.Id,
                    "https:" + d.Representations.Thumb,
                    "https:" + d.Image,
                    tags.Where(it => it.StartsWith("artist:")).Select(it => it.Replace("artist:", null)).ToArray(),
                    tags,
                    d.OriginalFormat,
                    d.Score
                ));
            }

            return imgs;
        }

        /// <summary>
        /// Gets a Query object and parses it into a Derpibooru-specific query string
        /// </summary>
        /// <param name="q"></param>
        /// <returns></returns>
        public static string BuildDerpibooru(this Query q)
        {
            // Base endpoint
            string query = "https://derpibooru.org/search.json?q=";

            // Tags
            query += q.Tags
                    .TrimEnd(',')
                    .TrimEnd(' ')
                    .Replace(" ", "+")
                    .Replace(",", "%2C");

            // Rating
            string rating = "";

            if (q.Ratings.Contains(Rating.Safe))
                rating += "safe ";
            if (q.Ratings.Contains(Rating.Questionable))
                rating += "questionable ";
            if (q.Ratings.Contains(Rating.Explicit))
                rating += "explicit ";
            rating = rating.TrimEnd(' ').Replace(" ", "+OR+");

            if (rating != "")
                rating = "%2C+(" + rating + ")";

            query += rating;

            //Prepare score query
            string score = "";

            if (q.MinScore != null && q.MaxScore != null)
            {
                score += "(score.gte:" + q.MinScore;
                score += " AND ";
                score += "score.lte:" + q.MaxScore;
                score += ")";
            }
            else
            {
                if (q.MinScore!= null)
                    score += "score.gte:" + q.MinScore;
                if (q.MaxScore != null)
                    score += "score.lte:" + q.MaxScore;
            }

            if (score != "")
                score = "%2C+" + score;

            query += score;

            // Add page number
            query += "&page=" + q.Page;

            // Add token
            if (!string.IsNullOrEmpty(q.Token))
                query += "&key=" + q.Token;

            return query;

        }
    }
}
